package com.cq.hd.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.entity.hf.HfBankPay;
import com.cq.hd.common.entity.hf.HfJsPay;
import com.cq.hd.common.entity.hf.HfTradeQuery;
import com.cq.hd.common.enums.ResponseEnums;
import com.cq.hd.common.enums.biz.*;
import com.cq.hd.common.pagination.Page;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.*;
import com.cq.hd.member.api.dto.*;
import com.cq.hd.member.api.vo.*;
import com.cq.hd.member.config.LockUtils;
import com.cq.hd.member.mapper.*;
import com.cq.hd.member.po.*;
import com.cq.hd.member.service.TbMemberCardService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cq.hd.system.api.HfApi;
import com.cq.hd.system.api.HfRequestRecordApi;
import com.cq.hd.system.api.dto.HfRequestRecordSaveDto;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 次卡表 服务实现类
 * </p>
 *
 * @author mYunYu
 * @since 2023-11-19
 */
@Slf4j
@Service
public class TbMemberCardServiceImpl extends ServiceImpl<TbMemberCardMapper, TbMemberCardPo> implements TbMemberCardService {

    @Autowired
    private TbBusinessMapper businessMapper;

    @Autowired
    private TbMemberCardBillMapper memberCardBillMapper;

    @Autowired
    private TbAppUserMapper appUserMapper;

    @Autowired
    private TbBankPayRecordMapper bankPayRecordMapper;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private HfApi hfApi;

    @Autowired
    private HfRequestRecordApi hfRequestRecordApi;

    @Override
    public Page<MemberCardPageVo> pageMemberCard(MemberCardPageDto memberCardPageDto) {
        PageHelper.startPage(memberCardPageDto.getPageNum(), memberCardPageDto.getPageSize());
        List<MemberCardPageVo> memberCardPageVos = baseMapper.listMemberCard(memberCardPageDto);
        PageInfo<MemberCardPageVo> pageInfo = new PageInfo<>(memberCardPageVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public Long saveMemberCard(MemberCardSaveDto memberCardSaveDto) {
        String cardName = memberCardSaveDto.getCardName();
        BigDecimal cardCost = memberCardSaveDto.getCardCost();
        Integer activeCount = memberCardSaveDto.getActiveCount();
        Integer cardSort = memberCardSaveDto.getCardSort();

        if (StringUtils.isBlank(cardName)) {
            Throw.isBusinessException("请输入次卡名称");
        }

        if (cardName.length() > 10) {
            Throw.isBusinessException("次卡名称最多输入10个字");
        }

        if (cardCost == null || cardCost.compareTo(new BigDecimal("1")) < 0) {
            Throw.isBusinessException("次卡费用必须大于1元");
        }

        if (cardCost.compareTo(new BigDecimal("99999999")) > 0) {
            Throw.isBusinessException("次卡费用必须小于99999999元");
        }

        if (activeCount == null || activeCount <= 0) {
            Throw.isBusinessException("活动发布次数必须大于0个");
        }

        if (activeCount > 1000000) {
            Throw.isBusinessException("活动发布次数不能超过1000000次");
        }

        if (cardSort == null || cardSort <= 0) {
            Throw.isBusinessException("排序必须大于0");
        }

        if (cardSort > 1000000) {
            Throw.isBusinessException("排序不能超过1000000");
        }

        // 次卡名称不能重复
        Integer count = baseMapper.selectCount(new QueryWrapper<TbMemberCardPo>().eq("del_state", 0)
                .eq("card_name", memberCardSaveDto.getCardName()));
        if (count != null && count > 0) {
            Throw.isBusinessException("次卡名称已存在");
        }

        TbMemberCardPo tbMemberCardPo = new TbMemberCardPo();
        BeanUtils.copyProperties(memberCardSaveDto, tbMemberCardPo);
        // 显示状态(1-显示，2-隐藏)
        tbMemberCardPo.setShowState(1);
        tbMemberCardPo.setCreateTime(LocalDateTime.now());
        tbMemberCardPo.setUpdateTime(LocalDateTime.now());

        int insert = baseMapper.insert(tbMemberCardPo);
        if (insert == 0) {
            Throw.isBusinessException("保存次卡数据失败");
        }

        return tbMemberCardPo.getId();
    }

    @Override
    public Boolean updateMemberCard(MemberCardUpdateDto memberCardUpdateDto) {
        String cardName = memberCardUpdateDto.getCardName();
        BigDecimal cardCost = memberCardUpdateDto.getCardCost();
        Integer activeCount = memberCardUpdateDto.getActiveCount();
        Integer cardSort = memberCardUpdateDto.getCardSort();

        if (StringUtils.isBlank(cardName)) {
            Throw.isBusinessException("请输入次卡名称");
        }

        if (cardName.length() > 10) {
            Throw.isBusinessException("次卡名称最多输入10个字");
        }

        if (cardCost == null || cardCost.compareTo(new BigDecimal("1")) < 0) {
            Throw.isBusinessException("次卡费用必须大于1元");
        }

        if (cardCost.compareTo(new BigDecimal("99999999")) > 0) {
            Throw.isBusinessException("次卡费用必须小于99999999元");
        }

        if (activeCount == null || activeCount <= 0) {
            Throw.isBusinessException("活动发布次数必须大于0个");
        }

        if (activeCount > 1000000) {
            Throw.isBusinessException("活动发布次数不能超过1000000次");
        }

        if (cardSort == null || cardSort <= 0) {
            Throw.isBusinessException("排序必须大于0");
        }

        if (cardSort > 1000000) {
            Throw.isBusinessException("排序不能超过1000000");
        }

        TbMemberCardPo tbMemberCardPo = baseMapper.selectById(memberCardUpdateDto.getId());
        if (tbMemberCardPo == null) {
            Throw.isBusinessException("未找到次卡数据");
        }

        // 次卡名称不能重复
        List<TbMemberCardPo> memberCardPos = baseMapper.selectList(new QueryWrapper<TbMemberCardPo>().eq("del_state", 0)
                .eq("card_name", memberCardUpdateDto.getCardName()));
        if (!CollectionUtils.isEmpty(memberCardPos)) {
            if (memberCardPos.size() > 1) {
                Throw.isBusinessException("次卡名称已存在");
            }

            if (!memberCardPos.get(0).getId().equals(memberCardUpdateDto.getId())) {
                Throw.isBusinessException("次卡名称已存在");
            }
        }

        BeanUtils.copyProperties(memberCardUpdateDto, tbMemberCardPo);
        tbMemberCardPo.setUpdateTime(LocalDateTime.now());
        int update = baseMapper.updateById(tbMemberCardPo);
        if (update == 0) {
            Throw.isBusinessException("更新次卡数据失败");
        }

        return true;
    }

    @Override
    public Page<AppMemberCardPageVo> pageAppMemberCard(AppMemberCardPageDto appMemberCardPageDto) {
        PageHelper.startPage(appMemberCardPageDto.getPageNum(), appMemberCardPageDto.getPageSize());
        List<AppMemberCardPageVo> appMemberFeeConfigPageVos = baseMapper.listAppMemberCard(appMemberCardPageDto);
        PageInfo<AppMemberCardPageVo> pageInfo = new PageInfo<>(appMemberFeeConfigPageVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public String createAppMemberCardOrder(AppMemberCardCreateDto appMemberCardCreateDto) {
        Long id = appMemberCardCreateDto.getId();
        if (id == null || id <= 0) {
            Throw.isBusinessException("请选择卡类型");
        }

        Integer payType = appMemberCardCreateDto.getPayType();
        if (payType == null || PayTypeEnum.typeOf(payType) == null) {
            Throw.isBusinessException("请选择支付方式");
        }

        TbBusinessPo tbBusinessPo;
        Long userId = appMemberCardCreateDto.getUserId();
        Long businessId = appMemberCardCreateDto.getBusinessId();
        if (businessId == null || businessId <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                // 如果不是商家，则返回空
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            tbBusinessPo = tbBusinessPos.get(0);
            businessId = tbBusinessPo.getId();
            appMemberCardCreateDto.setBusinessId(businessId);
        } else {
            tbBusinessPo = businessMapper.selectById(businessId);
            if (tbBusinessPo == null || tbBusinessPo.getDelState() != 0) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }
        }

        LocalDateTime now = LocalDateTime.now();
        // 如果不是会员或会员已过期，则不能购买次卡
        LocalDateTime memberExpireTime = tbBusinessPo.getMemberExpireTime();
        if (memberExpireTime != null) {
            if (!memberExpireTime.isAfter(now)) {
                // 会员已过期
                Throw.isBusinessException("请先续费成为会员");
            }
        } else {
            // 当前商家不是会员
            Throw.isBusinessException("请先开通成为会员");
        }

        TbAppUserPo appUserPo = appUserMapper.selectById(userId);
        if (appUserPo == null || StringUtils.isBlank(appUserPo.getOpenid())) {
            Throw.isBusinessException("请先授权");
        }

        // 对商家id加锁
        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "createAppMemberCardOrder:" + businessId);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            TbMemberCardPo tbMemberCardPo = baseMapper.selectById(id);
            if (tbMemberCardPo == null || tbMemberCardPo.getDelState() != 0 || tbMemberCardPo.getShowState() != 1) {
                Throw.isBusinessException("未找到会员类型");
            }

            String orderNo = NoUtils.getMemberCardNo();

            TbMemberCardBillPo tbMemberCardBillPo = new TbMemberCardBillPo();
            tbMemberCardBillPo.setCardId(id);
            tbMemberCardBillPo.setOrderBusinessId(businessId);
            tbMemberCardBillPo.setOrderNo(orderNo);
            tbMemberCardBillPo.setCardName(tbMemberCardPo.getCardName());
            tbMemberCardBillPo.setCardCost(tbMemberCardPo.getCardCost());
            tbMemberCardBillPo.setPayType(payType);
            tbMemberCardBillPo.setPayState(PayStateEnum.WAIT.getValue());
            tbMemberCardBillPo.setActiveCount(tbMemberCardPo.getActiveCount());
            tbMemberCardBillPo.setRemainActiveCount(tbMemberCardPo.getActiveCount());
            tbMemberCardBillPo.setOrderTime(now);
            tbMemberCardBillPo.setCreateTime(now);
            tbMemberCardBillPo.setUpdateTime(now);
            int insert = memberCardBillMapper.insert(tbMemberCardBillPo);
            if (insert == 0) {
                Throw.isBusinessException("下单失败");
            }

            return orderNo;
        } finally {
            LockUtils.unlock(lockKey);
        }
    }

    @Override
    public AppMemberCardPayVo payAppMemberCardOrder(AppMemberCardPayDto appMemberCardPayDto) {
        String orderNo = appMemberCardPayDto.getOrderNo();
        if (StringUtils.isBlank(orderNo)) {
            Throw.isBusinessException("订单号不能为空");
        }

        Long userId = appMemberCardPayDto.getUserId();
        Long businessId = appMemberCardPayDto.getBusinessId();
        if (businessId == null || businessId <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            businessId = tbBusinessPos.get(0).getId();
            appMemberCardPayDto.setBusinessId(businessId);
        }

        LocalDateTime now = LocalDateTime.now();
        List<TbMemberCardBillPo> tbMemberCardBillPos = memberCardBillMapper.selectList(new QueryWrapper<TbMemberCardBillPo>().eq("del_state", 0)
                .eq("order_business_id", businessId)
                .eq("order_no", orderNo));
        if (CollectionUtils.isEmpty(tbMemberCardBillPos)) {
            Throw.isBusinessException("未找到订单数据");
        }

        TbMemberCardBillPo tbMemberCardBillPo = tbMemberCardBillPos.get(0);
        if (!PayStateEnum.WAIT.getValue().equals(tbMemberCardBillPo.getPayState())) {
            Throw.isBusinessException("订单已处理");
        }

        TbAppUserPo appUserPo = appUserMapper.selectById(userId);

        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
        String reqSeqId = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss") + GenerateUtil.getRandomNum(5);
        String timeExpire = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime.plusMinutes(30), "yyyyMMddHHmmss");

        HfJsPay hfJsPay = new HfJsPay();
        hfJsPay.setWxOpenid(appUserPo.getOpenid());
        hfJsPay.setReqSeqId(reqSeqId);
        hfJsPay.setReqDate(yyyyMMdd);
        hfJsPay.setTimeExpire(timeExpire);
        hfJsPay.setTransAmt(tbMemberCardBillPo.getCardCost().setScale(2, BigDecimal.ROUND_DOWN).toString());
        hfJsPay.setGoodsDesc(tbMemberCardBillPo.getCardName());
        hfJsPay.setAttach(PayAttachEnum.MEMBER_CARD_PAY.getName());
        JSONObject jsonObject = hfApi.jsPay(hfJsPay).unpack();
        if (jsonObject == null) {
            Throw.isBusinessException("下单失败");
        }

        JSONObject dataJSONObject = jsonObject.getJSONObject("data");
        String respCode = dataJSONObject.getString("resp_code");
        if (!"00000000".equals(respCode) && !"00000100".equals(respCode)) {
            Throw.isBusinessException("下单失败");
        }

        String payInfo = dataJSONObject.getString("pay_info");
//            String preOrderId = dataJSONObject.getString("pre_order_id");
        String partyOrderId = dataJSONObject.getString("party_order_id");
        if (StringUtils.isBlank(payInfo) || StringUtils.isBlank(partyOrderId)) {
            Throw.isBusinessException("下单失败");
        }

        tbMemberCardBillPo.setPreOrderId(partyOrderId);
        tbMemberCardBillPo.setHfReqSeqId(reqSeqId);
        tbMemberCardBillPo.setHfReqDate(yyyyMMdd);
        tbMemberCardBillPo.setPayState(PayStateEnum.PAYING.getValue());
        int update = memberCardBillMapper.updateById(tbMemberCardBillPo);
        if (update == 0) {
            Throw.isBusinessException("下单失败");
        }

        AppMemberCardPayVo appMemberCardPayVo = new AppMemberCardPayVo();
        appMemberCardPayVo.setOrderNo(payInfo);

        return appMemberCardPayVo;
    }

    @Override
    public Boolean jsPayCallback(JSONObject dataObj) {
        String subRespCode = dataObj.getString("sub_resp_code");
        String subRespDesc = dataObj.getString("sub_resp_desc");
        String hfMerchantNo = dataObj.getString("huifu_id");
        String reqDate = dataObj.getString("req_date");
        String reqSeqId = dataObj.getString("req_seq_id");
        // 交易状态	S：成功、F：失败；
        String transStat = dataObj.getString("trans_stat");

        // 添加汇付申请单记录（聚合支付下单回调，异步回调接口）
        HfRequestRecordSaveDto hfRequestRecordSaveDto = new HfRequestRecordSaveDto();
        hfRequestRecordSaveDto.setApplyType(HfRequestRecordApplyTypeEnum.WX_JS_ORDER_ASYNC.getValue());
        hfRequestRecordSaveDto.setRequestType(HfRequestRecordRequestTypeEnum.ASYNC.getValue());
        hfRequestRecordSaveDto.setApplyNo(PayAttachEnum.MEMBER_CARD_PAY.getName());
        hfRequestRecordSaveDto.setHuifuId(hfMerchantNo);
        hfRequestRecordSaveDto.setHfApplyNo(reqDate);
        hfRequestRecordSaveDto.setDataResult(JSON.toJSONString(dataObj));
        hfRequestRecordSaveDto.setReqSeqId(reqSeqId);
        hfRequestRecordSaveDto.setRespCode(subRespCode);
        hfRequestRecordSaveDto.setRespDesc(subRespDesc);
        hfRequestRecordSaveDto.setCreateTime(LocalDateTime.now());
        hfRequestRecordSaveDto.setUpdateTime(LocalDateTime.now());
        Boolean saveRequestRecordState = hfRequestRecordApi.saveRequestRecord(hfRequestRecordSaveDto).unpack();
        if (!saveRequestRecordState) {
            log.error("添加汇付申请单记录失败（聚合支付下单回调-购买次卡，异步回调接口），hfRequestRecordSaveDto：{}", JSON.toJSONString(hfRequestRecordSaveDto));
        }

        List<TbMemberCardBillPo> tbMemberCardBillPos = memberCardBillMapper.selectList(new QueryWrapper<TbMemberCardBillPo>().eq("del_state", 0)
                .eq("hf_req_seq_id", reqSeqId).eq("hf_req_date", reqDate));
        if (CollectionUtils.isEmpty(tbMemberCardBillPos)) {
            log.error("jsPay回调失败，未找到购买次卡订单数据，reqSeqId：{}，reqDate：{}", reqSeqId, reqDate);
            return false;
        }
        TbMemberCardBillPo tbMemberCardBillPo = tbMemberCardBillPos.get(0);

        if ("00000000".equals(subRespCode) && "S".equals(transStat)) {
            if (!PayStateEnum.PAYING.getValue().equals(tbMemberCardBillPo.getPayState())) {
                log.error("jsPay回调失败，购买次卡订单非待支付状态，orderId:{}", tbMemberCardBillPo.getId());
                return false;
            }

            // 如果交易成功，修改订单状态
            paySuccess(tbMemberCardBillPo);

            return true;
        }

        if ("F".equals(transStat)) {
            tbMemberCardBillPo.setPayState(PayStateEnum.FAIL.getValue());
            tbMemberCardBillPo.setPayFailReason(dataObj.getString("bank_message"));
            tbMemberCardBillPo.setUpdateTime(LocalDateTime.now());
            memberCardBillMapper.updateById(tbMemberCardBillPo);
        }

        return true;
    }

    @Override
    public Boolean queryOrderPay(AppMemberCardPayQueryDto appMemberCardPayQueryDto) {
        String orderNo = appMemberCardPayQueryDto.getOrderNo();
        if (StringUtils.isBlank(orderNo)) {
            Throw.isBusinessException("订单号不能为空");
        }

        Long userId = appMemberCardPayQueryDto.getUserId();
        Long businessId = appMemberCardPayQueryDto.getBusinessId();
        if (businessId == null || businessId <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            businessId = tbBusinessPos.get(0).getId();
            appMemberCardPayQueryDto.setBusinessId(businessId);
        }

        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "queryMemberCardOrderPay:" + orderNo);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            List<TbMemberCardBillPo> tbMemberCardBillPos = memberCardBillMapper.selectList(new QueryWrapper<TbMemberCardBillPo>().eq("del_state", 0)
                    .eq("order_business_id", businessId)
                    .eq("order_no", orderNo));
            if (CollectionUtils.isEmpty(tbMemberCardBillPos)) {
                log.error("查单失败，未找到购买次卡订单数据，orderNo：{}", orderNo);
                return false;
            }

            TbMemberCardBillPo tbMemberCardBillPo = tbMemberCardBillPos.get(0);
            if (!OrderStateEnum.PAYING.getValue().equals(tbMemberCardBillPo.getPayState())) {
                log.error("查单失败，购买次卡订单不是支付中状态，orderNo：{}", orderNo);
                return true;
            }

            // 调用hf查单接口，避免临界点出现支付情况，如果查单状态是支付成功，则修改状态为待核销
            HfTradeQuery hfTradeQuery = new HfTradeQuery();
            hfTradeQuery.setOrgReqDate(tbMemberCardBillPo.getHfReqDate());
            hfTradeQuery.setOrgReqSeqId(tbMemberCardBillPo.getHfReqSeqId());
            JSONObject jsonObject = hfApi.tradeQuery(hfTradeQuery).unpack();
            if (jsonObject != null) {
                JSONObject dataJSONObject = jsonObject.getJSONObject("data");
                // 交易状态	P：处理中；S：成功；F：失败；I: 初始（初始状态很罕见，请联系汇付技术人员处理）；
                String transStat = dataJSONObject.getString("trans_stat");
                // NOTPAY，订单未支付
                String bankCode = dataJSONObject.getString("bank_code");
                log.info("查单成功，购买次卡订单第三方交易状态：【{}】，orderNo：{}", transStat, orderNo);
                if ("S".equals(transStat)) {
                    paySuccess(tbMemberCardBillPo);
                    return true;
                }

                if ("F".equals(transStat)) {
                    // 查单是支付失败，将支付中--》支付失败
                    tbMemberCardBillPo.setPayState(PayStateEnum.FAIL.getValue());
                    tbMemberCardBillPo.setPayFailReason("超时未支付");
                    tbMemberCardBillPo.setUpdateTime(LocalDateTime.now());
                    memberCardBillMapper.updateById(tbMemberCardBillPo);
                }
            }
        } finally {
            LockUtils.unlock(lockKey);
        }

        return false;
    }

    private void paySuccess(TbMemberCardBillPo tbMemberCardBillPo) {
        Long orderBusinessId = tbMemberCardBillPo.getOrderBusinessId();

        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "memberCardPaySuccess:" + orderBusinessId);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            TbMemberCardBillPo memberCardBillPo = memberCardBillMapper.selectById(tbMemberCardBillPo.getId());
            if (!PayStateEnum.PAYING.getValue().equals(memberCardBillPo.getPayState())) {
                log.error("购买次卡订单支付成功处理，订单非支付中状态，orderId:{}", memberCardBillPo.getId());
                return;
            }

            tbMemberCardBillPo.setPayState(PayStateEnum.SUCCESS.getValue());
            tbMemberCardBillPo.setPayTime(LocalDateTime.now());
            tbMemberCardBillPo.setArriveTime(LocalDateTime.now());
            int update = memberCardBillMapper.updateById(tbMemberCardBillPo);
            if (update == 0) {
                log.error("购买次卡订单支付成功处理，更新次卡流水记录失败，orderId:{}", memberCardBillPo.getId());
                Throw.isBusinessException("下单失败");
            }
        } finally {
            LockUtils.unlock(lockKey);
        }
    }

    @Override
    public MemberCardPageVo detailById(Long id) {
        TbMemberCardPo tbMemberCardPo = baseMapper.selectById(id);
        if (tbMemberCardPo != null && tbMemberCardPo.getShowState() == 1 && tbMemberCardPo.getDelState() == 0) {
            MemberCardPageVo memberCardPageVo = new MemberCardPageVo();
            BeanUtils.copyProperties(tbMemberCardPo, memberCardPageVo);

            return memberCardPageVo;
        }

        return null;
    }

    @Override
    public BankPayRechargeVo bankPayAppMemberCardOrder(AdminBusinessMemberCardPayDto adminBusinessMemberCardPayDto) {
        Long id = adminBusinessMemberCardPayDto.getId();
        if (id == null || id <= 0) {
            Throw.isBusinessException("请选择次卡类型");
        }

        TbMemberCardPo tbMemberCardPo = baseMapper.selectById(id);
        if (tbMemberCardPo == null || tbMemberCardPo.getShowState() != 1 || tbMemberCardPo.getDelState() != 0) {
            Throw.isBusinessException("未找到次卡数据");
        }

        Long businessId = adminBusinessMemberCardPayDto.getBusinessId();
        TbBusinessPo businessPo = businessMapper.selectById(businessId);
        String hfMerchantNo = businessPo.getHfMerchantNo();
        if (StringUtils.isBlank(hfMerchantNo)) {
            log.error("网银购买次卡失败，未正式入驻成功的商家不能使用网银支付，businessId：{}", businessId);
            Throw.isBusinessException("未正式入驻成功的商家不能使用网银支付");
        }

        BigDecimal rechargeAmt = tbMemberCardPo.getCardCost();
        // 交易金额=输入充值金额+网银手续费
        BigDecimal tradeAmt = rechargeAmt.add(Constant.BANK_PAY_AMT);

        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
        String reqSeqId = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss") + GenerateUtil.getRandomNum(5);

        LocalDateTime timeExpireLocalDateTime = nowLocalDateTime.plusMinutes(120);
        String timeExpire = LocalDateUtil.toLocalDateTimeToString(timeExpireLocalDateTime, "yyyyMMddHHmmss");

        // 调用hf网银支付接口
        HfBankPay hfBankPay = new HfBankPay();
//        hfBankPay.setHuifuId(hfMerchantNo);
        hfBankPay.setReqSeqId(reqSeqId);
        hfBankPay.setReqDate(yyyyMMdd);
        hfBankPay.setTimeExpire(timeExpire);
        hfBankPay.setTransAmt(tradeAmt.toString());
        hfBankPay.setGoodsDesc("火动会员-" + tbMemberCardPo.getCardName());
        hfBankPay.setRequestIp(adminBusinessMemberCardPayDto.getRequestIp());
        hfBankPay.setRemark(String.valueOf(BankPayTradeTypeEnum.MERCHANT_CARD.getValue()));
        JSONObject jsonObject = hfApi.bankPay(hfBankPay).unpack();
        if (jsonObject == null) {
            log.error("网银购买次卡失败，调用hf网银支付接口失败，businessId：{}", businessId);
            Throw.isBusinessException("下单失败，请联系客服");
        }

        JSONObject dataJSONObject = jsonObject.getJSONObject("data");
        String respCode = dataJSONObject.getString("resp_code");
        String respDesc = dataJSONObject.getString("resp_desc");
        if (!"00000000".equals(respCode)) {
            Throw.isBusinessException(respDesc);
        }

        String formUrl = dataJSONObject.getString("form_url");
        // P：处理中，S：成功，F：失败，I：初始化（停留在操作页面没选银行支付会是I状态）；
        String transStat = dataJSONObject.getString("trans_stat");

        if (StringUtils.isBlank(formUrl)) {
            log.error("网银购买次卡失败，获取网银跳转链接数据为空，businessId：{}，memberFeeConfigId：{}", businessId, id);
            Throw.isBusinessException("下单失败，请联系客服");
        }

        int tradeState = BankPayTradeStateEnum.WAIT_PAY.getValue();
        if ("P".equals(transStat)) {
            tradeState = BankPayTradeStateEnum.PROCESSING.getValue();
        } else if ("S".equals(transStat)) {
            tradeState = BankPayTradeStateEnum.SUCCESS.getValue();
        } else if ("F".equals(transStat)) {
            tradeState = BankPayTradeStateEnum.FAIL.getValue();
        }

        LocalDateTime now = LocalDateTime.now();
        String bankPayOrderNo = NoUtils.getBankPayOrderNo();

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            // 添加购买次卡流水和网银支付记录
            TbMemberCardBillPo tbMemberCardBillPo = new TbMemberCardBillPo();
            tbMemberCardBillPo.setCardId(id);
            tbMemberCardBillPo.setOrderBusinessId(businessId);
            tbMemberCardBillPo.setOrderNo(NoUtils.getMemberCardNo());
            tbMemberCardBillPo.setCardName(tbMemberCardPo.getCardName());
            tbMemberCardBillPo.setCardCost(tbMemberCardPo.getCardCost());
            tbMemberCardBillPo.setPayType(PayTypeEnum.BANK.getValue());
            tbMemberCardBillPo.setPayState(PayStateEnum.WAIT.getValue());
            tbMemberCardBillPo.setActiveCount(tbMemberCardPo.getActiveCount());
            tbMemberCardBillPo.setRemainActiveCount(tbMemberCardPo.getActiveCount());
            tbMemberCardBillPo.setOrderTime(now);
            tbMemberCardBillPo.setCreateTime(now);
            tbMemberCardBillPo.setUpdateTime(now);
            int insert = memberCardBillMapper.insert(tbMemberCardBillPo);
            if (insert == 0) {
                log.error("网银购买次卡失败，添加购买次卡记录失败，businessId：{}", businessId);
                Throw.isBusinessException("下单失败，请联系客服");
            }

            TbBankPayRecordPo tbBankPayRecordPo = new TbBankPayRecordPo();
            tbBankPayRecordPo.setBusinessId(businessId);
            tbBankPayRecordPo.setUserId(adminBusinessMemberCardPayDto.getUserId());
            tbBankPayRecordPo.setOrderNo(bankPayOrderNo);
            tbBankPayRecordPo.setTradeType(BankPayTradeTypeEnum.MERCHANT_CARD.getValue());
            tbBankPayRecordPo.setRelationTradeNo(tbMemberCardBillPo.getOrderNo());
            tbBankPayRecordPo.setHfId(hfMerchantNo);
            tbBankPayRecordPo.setReqSeqId(reqSeqId);
            tbBankPayRecordPo.setReqDate(yyyyMMdd);
            tbBankPayRecordPo.setTimeExpire(timeExpire);
            tbBankPayRecordPo.setRequestIp(adminBusinessMemberCardPayDto.getRequestIp());
            tbBankPayRecordPo.setTradeAmt(tradeAmt);
            tbBankPayRecordPo.setFeeAmt(Constant.BANK_PAY_AMT);
            tbBankPayRecordPo.setReceiveAmt(rechargeAmt);
            tbBankPayRecordPo.setTradeState(tradeState);
            tbBankPayRecordPo.setAcctState(BankPayTradeStateEnum.WAIT_PAY.getValue());
            tbBankPayRecordPo.setTradeTime(now);
            tbBankPayRecordPo.setCreateTime(now);
            tbBankPayRecordPo.setUpdateTime(now);
            insert = bankPayRecordMapper.insert(tbBankPayRecordPo);
            if (insert == 0) {
                log.error("网银购买次卡失败，添加网银支付记录失败，businessId：{}", businessId);
                Throw.isBusinessException("下单失败，请联系客服");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<网银支付购买次卡>事务异常回滚", e);
            Throw.isBusinessException(e.getMessage());
        }

        BankPayRechargeVo bankPayRechargeVo = new BankPayRechargeVo();
        bankPayRechargeVo.setFromUrl(formUrl);
        bankPayRechargeVo.setOrderNo(bankPayOrderNo);

        return bankPayRechargeVo;
    }

    @Override
    public BankPayQueryVo queryBankPayOrder(BankPayQueryDto bankPayQueryDto) {
        String orderNo = bankPayQueryDto.getOrderNo();
        if (StringUtils.isBlank(orderNo)) {
            Throw.isBusinessException("订单号不能为空");
        }

        List<TbBankPayRecordPo> tbBankPayRecordPos = bankPayRecordMapper.selectList(new QueryWrapper<TbBankPayRecordPo>().eq("del_state", 0)
                .eq("order_no", orderNo)
                .orderByDesc("create_time"));
        if (CollectionUtils.isEmpty(tbBankPayRecordPos)) {
            log.error("查单失败，未找到网银支付订单数据，orderNo：{}", orderNo);
            Throw.isBusinessException("未找到订单");
        }

        TbBankPayRecordPo tbBankPayRecordPo = tbBankPayRecordPos.get(0);
        // 交易状态(1-待支付，2-处理中，3-成功，4-失败)
        Integer tradeState = tbBankPayRecordPo.getTradeState();

        BankPayQueryVo bankPayQueryVo = new BankPayQueryVo();
        bankPayQueryVo.setTradeState(tradeState);

        if (BankPayTradeStateEnum.SUCCESS.getValue().equals(tradeState) || BankPayTradeStateEnum.FAIL.getValue().equals(tradeState)) {
            return bankPayQueryVo;
        }

        // 如果是待支付/处理中交易状态，需要调用hf接口做查单处理
        HfTradeQuery hfTradeQuery = new HfTradeQuery();
        hfTradeQuery.setHfMerchantNo(tbBankPayRecordPo.getHfId());
        hfTradeQuery.setOrgReqDate(tbBankPayRecordPo.getReqDate());
        hfTradeQuery.setOrgReqSeqId(tbBankPayRecordPo.getReqSeqId());
        JSONObject jsonObject = hfApi.bankPayQuery(hfTradeQuery).unpack();
        if (jsonObject != null) {
            JSONObject dataJSONObject = jsonObject.getJSONObject("data");
            // P：处理中，S：成功，F：失败，I：初始化（停留在操作页面没选银行支付会是I状态）；
            String transStat = dataJSONObject.getString("trans_stat");
            log.info("查网银支付订单成功，订单第三方交易状态：【{}】，orderNo：{}", transStat, orderNo);

            if ("S".equals(transStat)) {
                // 支付成功，更新网银支付记录状态，增加补贴金，增加补贴金流水数据
                tbBankPayRecordPo.setTradeState(BankPayTradeStateEnum.SUCCESS.getValue());
                tbBankPayRecordPo.setCallbackTime(LocalDateTime.now());
                tbBankPayRecordPo.setUpdateTime(LocalDateTime.now());
                // hf全局流水号
                tbBankPayRecordPo.setHfSeqId(dataJSONObject.getString("org_hf_seq_id"));

                JSONObject bankExtendParamData = dataJSONObject.getJSONObject("bank_extend_param_data");
                if (bankExtendParamData != null) {
                    // 付款方银行号
                    tbBankPayRecordPo.setBankId(bankExtendParamData.getString("bank_id"));
                    // 付款方银行账户
                    tbBankPayRecordPo.setPyerAcctId(bankExtendParamData.getString("pyer_acct_id"));
                    // 付款方银行账户名
                    tbBankPayRecordPo.setPyerAcctNm(bankExtendParamData.getString("pyer_acct_nm"));
                }

                // 更新网银支付记录状态，更新次卡下单流水
                bankPaySuccess(tbBankPayRecordPo);
                bankPayQueryVo.setTradeState(BankPayTradeStateEnum.SUCCESS.getValue());
            } else if ("F".equals(transStat)) {
                // 支付失败，更新网银支付记录状态和失败原因
                String bankDesc = dataJSONObject.getString("bank_desc");

                tbBankPayRecordPo.setTradeState(BankPayTradeStateEnum.FAIL.getValue());
                tbBankPayRecordPo.setFailReason(bankDesc);
                tbBankPayRecordPo.setHfFailReason(bankDesc);
                tbBankPayRecordPo.setCallbackTime(LocalDateTime.now());
                tbBankPayRecordPo.setUpdateTime(LocalDateTime.now());
                bankPayRecordMapper.updateById(tbBankPayRecordPo);

                bankPayQueryVo.setTradeState(BankPayTradeStateEnum.FAIL.getValue());
            } else if ("P".equals(transStat)) {
                // 处理中，更新网银支付记录状态
                tbBankPayRecordPo.setTradeState(BankPayTradeStateEnum.PROCESSING.getValue());
                tbBankPayRecordPo.setUpdateTime(LocalDateTime.now());
                bankPayRecordMapper.updateById(tbBankPayRecordPo);

                bankPayQueryVo.setTradeState(BankPayTradeStateEnum.PROCESSING.getValue());
            }
        }

        return bankPayQueryVo;
    }

    private void bankPaySuccess(TbBankPayRecordPo tbBankPayRecordPo) {
        // 根据订单号查询网银待支付的开卡记录
        List<TbMemberCardBillPo> tbMemberCardBillPos = memberCardBillMapper.selectList(new QueryWrapper<TbMemberCardBillPo>()
                .eq("del_state", 0)
                .eq("pay_type", PayTypeEnum.BANK.getValue())
                .eq("order_no", tbBankPayRecordPo.getOrderNo())
                .eq("pay_state", PayStateEnum.WAIT.getValue())
                .orderByDesc("order_time"));

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            // 更新次卡购买流水状态
            if (!CollectionUtils.isEmpty(tbMemberCardBillPos)) {
                TbMemberCardBillPo tbMemberCardBillPo = tbMemberCardBillPos.get(0);

                tbMemberCardBillPo.setPayState(PayStateEnum.SUCCESS.getValue());
                tbMemberCardBillPo.setPayTime(LocalDateTime.now());
                tbMemberCardBillPo.setArriveTime(LocalDateTime.now());
                int update = memberCardBillMapper.updateById(tbMemberCardBillPo);
                if (update == 0) {
                    log.error("网银购买次卡订单支付成功处理，更新次卡流水记录失败，orderId:{}", tbMemberCardBillPo.getId());
                    Throw.isBusinessException("下单失败");
                }
            }

            // 更新网银支付记录状态
            int count = bankPayRecordMapper.updateById(tbBankPayRecordPo);
            if (count == 0) {
                log.error("网银购买次卡订单支付成功处理，更新网银支付记录失败，bankPayRecordId:{}", tbBankPayRecordPo.getId());
                Throw.isBusinessException("更新网银支付记录失败");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<网银支付购买次卡>事务异常回滚", e);
        }
    }

    @Override
    public Boolean bankPayCallback(JSONObject dataObj) {
        String subRespCode = dataObj.getString("sub_resp_code");
        String subRespDesc = dataObj.getString("sub_resp_desc");
        String hfMerchantNo = dataObj.getString("huifu_id");
        String reqDate = dataObj.getString("req_date");
        String reqSeqId = dataObj.getString("req_seq_id");
        //   // P：处理中，S：成功，F：失败，I：初始化（停留在操作页面没选银行支付会是I状态）；
        String transStat = dataObj.getString("trans_stat");
        //   // P：处理中，S：成功，F：失败，I：初始化（停留在操作页面没选银行支付会是I状态）；
        String acctStat = dataObj.getString("acct_stat");
        // 通知类型	1：通道通知，2：财务通知；
        String notifyType = dataObj.getString("notify_type");

        // 根据reqSeqId+reqDate查询网银支付记录
        List<TbBankPayRecordPo> tbBankPayRecordPos = bankPayRecordMapper.selectList(new QueryWrapper<TbBankPayRecordPo>().eq("del_state", 0)
                .eq("trade_type", BankPayTradeTypeEnum.MERCHANT_CARD.getValue())
                .eq("req_date", reqDate)
                .eq("req_seq_id", reqSeqId).orderByDesc("create_time"));
        if (CollectionUtils.isEmpty(tbBankPayRecordPos)) {
            log.error("网银购买次卡回调, 未找到网银支付记录数据, reqSeqId:{}, reqDate:{}", reqSeqId, reqDate);
            return true;
        }

        TbBankPayRecordPo tbBankPayRecordPo = tbBankPayRecordPos.get(0);

        // 添加汇付申请单记录（网银支付下单回调，异步回调接口）
        HfRequestRecordSaveDto hfRequestRecordSaveDto = new HfRequestRecordSaveDto();
        hfRequestRecordSaveDto.setApplyType(HfRequestRecordApplyTypeEnum.BANK_PAY_ASYNC.getValue());
        hfRequestRecordSaveDto.setRequestType(HfRequestRecordRequestTypeEnum.ASYNC.getValue());
        hfRequestRecordSaveDto.setApplyNo(PayAttachEnum.MEMBER_CARD_PAY.getName());
        hfRequestRecordSaveDto.setHuifuId(hfMerchantNo);
        hfRequestRecordSaveDto.setHfApplyNo(tbBankPayRecordPo.getOrderNo());
        hfRequestRecordSaveDto.setDataResult(JSON.toJSONString(dataObj));
        hfRequestRecordSaveDto.setReqSeqId(reqSeqId);
        hfRequestRecordSaveDto.setRespCode(subRespCode);
        hfRequestRecordSaveDto.setRespDesc(subRespDesc);
        hfRequestRecordSaveDto.setCreateTime(LocalDateTime.now());
        hfRequestRecordSaveDto.setUpdateTime(LocalDateTime.now());
        Boolean saveRequestRecordState = hfRequestRecordApi.saveRequestRecord(hfRequestRecordSaveDto).unpack();
        if (!saveRequestRecordState) {
            log.error("添加汇付申请单记录失败（网银支付下单回调-购买次卡，异步回调接口），hfRequestRecordSaveDto：{}", JSON.toJSONString(hfRequestRecordSaveDto));
        }

        if (BankPayTradeStateEnum.FAIL.getValue().equals(tbBankPayRecordPo.getTradeState())
                || BankPayTradeStateEnum.SUCCESS.getValue().equals(tbBankPayRecordPo.getTradeState())) {
            log.error("网银购买次卡回调, 订单已处理, reqSeqId:{}, reqDate:{}", reqSeqId, reqDate);
            return true;
        }

        if ("00000000".equals(subRespCode)) {
            if ("S".equals(transStat)) {
                // 交易成功
                if ("S".equals(acctStat)) {
                    // 入账成功
                    bankPaySuccess(tbBankPayRecordPo);
                } else {
                    // 只更新财务状态,但不更新交易状态,也不增加资金
                    if ("P".equals(acctStat)) {
                        bankPayRecordMapper.updateAcctState(tbBankPayRecordPo.getId(), BankPayTradeStateEnum.PROCESSING.getValue());
                    } else if ("F".equals(acctStat)) {
                        bankPayRecordMapper.updateAcctState(tbBankPayRecordPo.getId(), BankPayTradeStateEnum.FAIL.getValue());
                    }
                }
            } else if ("F".equals(transStat)) {
                tbBankPayRecordPo.setTradeState(BankPayTradeStateEnum.FAIL.getValue());
                tbBankPayRecordPo.setFailReason(dataObj.getString("bank_desc"));
                tbBankPayRecordPo.setHfFailReason(JSON.toJSONString(dataObj));
                bankPayRecordMapper.updateById(tbBankPayRecordPo);
            }
        } else {
            if ("F".equals(transStat)) {
                tbBankPayRecordPo.setTradeState(BankPayTradeStateEnum.FAIL.getValue());
                tbBankPayRecordPo.setFailReason(dataObj.getString("bank_desc"));
                tbBankPayRecordPo.setHfFailReason(JSON.toJSONString(dataObj));
                bankPayRecordMapper.updateById(tbBankPayRecordPo);
            }
        }

        return true;
    }
}
